﻿/* *
 * =============================================================================
 * File Name:               Connection.cs
 * Programmer:              Ken Watts
 * Creation Date:           8/3/2008
 * =============================================================================
 * Description:             Class that represents a connection between devices.
 * =============================================================================
 * Modification Date:       8/3/2008 - Initial Revision
 * =============================================================================
 * */

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace DigitalLogicSimulator
{
    public class Connection : Canvas
    {
        // Internal data
        bool trackingMouseMove = false;
        Color strokeColor;
        Line connectionLine;
        Device startDevice;
        Point startPoint, endPoint;

        public Connection(Device inStartDevice, Point inStartPoint, Point inEndPoint)
        {
            Loaded += new RoutedEventHandler(Connection_Loaded);
            strokeColor = Color.FromArgb(0xaa, 0, 0, 0);
            // Setup references
            startDevice = inStartDevice;
            startPoint = inStartPoint;
            endPoint = inEndPoint;
        }

        public void Delete()
        {
            // Hide the connection
            connectionLine.Visibility = Visibility.Collapsed;
        }

        void Connection_Loaded(object sender, RoutedEventArgs e)
        {
            connectionLine = new Line();
            connectionLine.Stroke = new SolidColorBrush(strokeColor);
            connectionLine.StrokeThickness = Device.k_dbl_stroke_thickness;
            connectionLine.X1 = startPoint.X;
            connectionLine.Y1 = startPoint.Y;
            connectionLine.X2 = endPoint.X;
            connectionLine.Y2 = endPoint.Y;
            connectionLine.MouseLeftButtonDown += new MouseButtonEventHandler(CustomMouseLeftButtonDown);
            connectionLine.MouseLeftButtonUp += new MouseButtonEventHandler(CustomMouseLeftButtonUp);
            connectionLine.MouseMove += new MouseEventHandler(CustomMouseMove);
            Panel parentPanel = (Panel)Parent;
            parentPanel.Children.Add(connectionLine);
        }

        public void Redraw(Point inStartPoint, Point inEndPoint)
        {
            startPoint = inStartPoint;
            endPoint = inEndPoint;
            connectionLine.X1 = startPoint.X;
            connectionLine.Y1 = startPoint.Y;
            connectionLine.X2 = endPoint.X;
            connectionLine.Y2 = endPoint.Y;
        }

        protected void CustomMouseLeftButtonDown(
            object sender, MouseButtonEventArgs e)
        {
            // Remove this connection from the start
            if (!startDevice.Disconnect(this))
                return;

            // Reset z-orders
            Panel parentPanel = (Panel)Parent;
            int topMost = 0, zOrder;
            for (int i = 0; i < parentPanel.Children.Count; i++)
                if (parentPanel.Children[i] is Device)
                {
                    Device dev = (Device)parentPanel.Children[i];
                    // Determine the z-order of all item
                    zOrder = (int)dev.GetValue(Canvas.ZIndexProperty);
                    if (zOrder > topMost)
                        topMost = zOrder;
                }
            // Set this above the rest
            connectionLine.SetValue(Canvas.ZIndexProperty, topMost + 1);

            connectionLine.X2 = e.GetPosition(this).X;
            connectionLine.Y2 = e.GetPosition(this).Y;

            trackingMouseMove = true;
            FrameworkElement fe = sender as FrameworkElement;

            if (fe != null)
            {
                fe.CaptureMouse();
            }
        }

        protected void CustomMouseMove(object sender, MouseEventArgs e)
        {
            if (trackingMouseMove)
            {
                connectionLine.X2 = e.GetPosition(this).X;
                connectionLine.Y2 = e.GetPosition(this).Y;
                // Determine if device should be highlighted
                Panel parent = (Panel)Parent;
                for (int i = 0; i < parent.Children.Count; i++)
                    if (parent.Children[i] is Device)
                    {
                        Device dev = (Device)parent.Children[i];
                        double xScale = 1, yScale = 1;
                        if (Application.Current.Host.Content.IsFullScreen)
                        {
                            xScale = Application.Current.Host.Content.ActualWidth / parent.ActualWidth;
                            yScale = Application.Current.Host.Content.ActualHeight / parent.ActualHeight;
                        }
                        // if the mouse is over another shape, highlight it
                        if (dev.Contains(new Point(e.GetPosition(parent).X * xScale, e.GetPosition(parent).Y * yScale)))
                            dev.Highlight(true);
                        else
                            dev.Highlight(false);
                    }
            }
        }

        protected void CustomMouseLeftButtonUp(
            object sender, MouseButtonEventArgs e)
        {
            if (trackingMouseMove)
            {
                FrameworkElement fe = sender as FrameworkElement;
                fe.ReleaseMouseCapture();
                trackingMouseMove = false;
                // Hide this line
                connectionLine.Visibility = System.Windows.Visibility.Collapsed;
                // Determine if device should be highlighted
                Panel parent = (Panel)Parent;
                for (int i = 0; i < parent.Children.Count; i++)
                    if (parent.Children[i] is Device)
                    {
                        Device dev = (Device)parent.Children[i];
                        double xScale = 1, yScale = 1;
                        if (Application.Current.Host.Content.IsFullScreen)
                        {
                            xScale = Application.Current.Host.Content.ActualWidth / parent.ActualWidth;
                            yScale = Application.Current.Host.Content.ActualHeight / parent.ActualHeight;
                        }
                        // if the mouse is over another shape, highlight it
                        if (dev.IsHighlighted())
                        {
                            // Remove highlighting
                            dev.Highlight(false);
                            // Establish a new connection
                            Point endPoint = startDevice.MakeConnection(dev, new Point(e.GetPosition(parent).X * xScale,
                                e.GetPosition(parent).Y * yScale), this);
                            connectionLine.X2 = endPoint.X;
                            connectionLine.Y2 = endPoint.Y;
                            connectionLine.Visibility = System.Windows.Visibility.Visible;
                        }
                    }
            }
        }
    }
}
